package lol.clann.bukkit.pluginboot.service;

import lol.clann.bukkit.pluginboot.task.BukkitTimer;
import lol.clann.bukkit.pluginboot.task.Task;
import lol.clann.bukkit.pluginboot.task.Timer;
import lol.clann.clannboot.context.ModuleContext;
import lol.clann.clannboot.model.LazyLoadLogger;
import lol.clann.clannboot.module.ConfigRef;
import lol.clann.clannboot.module.Module;
import lol.clann.clannboot.util.BaseUtils;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitTask;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author pyz
 * @date 2018/9/18 下午10:24
 */

public class ExecutorService {
    private static LazyLoadLogger logger = new LazyLoadLogger(ModuleContext.rootModuleId);
    /**
     * 线程池
     */
    private static java.util.concurrent.ExecutorService worker = new ThreadPoolExecutor(8, 16, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());

    public static void timer(String moduleId, Timer config, Runnable runnable) {
        Module module = ModuleContext.getModule(moduleId);
        long dely = ConfigRef.parseValue(moduleId, config.dely(), Long.class);
        long interval = ConfigRef.parseValue(moduleId, config.interval(), Long.class);
        Thread t = new Thread(() -> {
            if (dely > 0) {
                BaseUtils.dely(dely);
            }
            while (module.isRunning()) {
                if (config.async()) {
                    // 异步
                    worker.execute(runnable);
                } else {
                    // 同步
                    Bukkit.getScheduler().runTask(module.getExtend(), runnable);
                }
                BaseUtils.dely(interval);
            }
        });
        t.setName(config.name());
        t.start();
        module.add(() -> t.interrupt());
    }

    public static void bukkitTimer(String moduleId, BukkitTimer config, Runnable runnable) {
        Module module = ModuleContext.getModule(moduleId);
        long dely = ConfigRef.parseValue(moduleId, config.dely(), Long.class);
        long interval = ConfigRef.parseValue(moduleId, config.interval(), Long.class);
        BukkitTask task;
        if (config.async()) {
            task = Bukkit.getScheduler().runTaskTimerAsynchronously(module.getExtend(), runnable, dely, interval);
        } else {
            task = Bukkit.getScheduler().runTaskTimer(module.getExtend(), runnable, dely, interval);
        }
        module.add(() -> task.cancel());
    }

    public static void task(String moduleId, Task config, Runnable runnable) {
        Module module = ModuleContext.getModule(moduleId);
        long dely = ConfigRef.parseValue(moduleId, config.dely(), Long.class);
        Thread t = new Thread(() -> {
            if (dely > 0) {
                BaseUtils.dely(dely);
            }
            if (!module.isRunning()) {
                return;
            }
            Runnable run = () -> {
                do {
                    try {
                        runnable.run();
                    } catch (Throwable e) {
                        logger.getLogger().error("线程执行异常:" + config.toString(), e);
                    }
                } while (config.loop());
            };
            if (config.async()) {
                run.run();
            } else {
                // 如果是同步,说明会很快执行完毕,所以不用交给module管理
                Bukkit.getScheduler().runTask(module.getExtend(), () -> run.run());
            }
        });
        t.setName(config.name());
        t.start();
        module.add(() -> t.interrupt());
    }

}
